package com.taologs.search;

import org.ansj.lucene6.AnsjAnalyzer;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

import java.io.File;
import java.io.FileReader;

public class Indexer {
 
     private IndexWriter writer; // 写索引实例
     
     /**
      * 构造方法 实例化IndexWriter
      * @param indexDir 指定写入索引的目录
      * @throws Exception
      */
     public Indexer(String indexDir)throws Exception{
         Directory dir= FSDirectory.open(new File(indexDir).toPath()); //取索引存放的位置信息
         Analyzer analyzer=new AnsjAnalyzer(); // 标准分词器
         IndexWriterConfig iwc=new IndexWriterConfig(analyzer); //入分析器
         writer=new IndexWriter(dir, iwc); //据索引的路径参数和索引的配置参数,实例化索引
     }
     
     /**
      * 关闭写索引
      * @throws Exception
      */
     public void close()throws Exception{
         writer.close();
     }

     /**
      * 索引指定目录的所有文件
      * @param dataDir 需要进行索引的数据的目录
      * @throws Exception
      * return 返回索引的数目
      */
     public int index(String dataDir)throws Exception{
         File dir=new File(dataDir);
         if(dir.isDirectory()) {
             File[] files = new File(dataDir).listFiles(); //历该目录下的所有数据文件
             for(File f:files){
                 if(f.isFile()){
                     indexFile(f);
                 }else{
                     index(f.toString());
                 }; // 依次对每个文件进行索引
             }
         }

         return writer.numDocs();    // 返回索引的文件数目
     }
 
     /**
      * 索引指定文件
      * @param f 指定的待索引的文件
      */
     private void indexFile(File f) throws Exception{
         System.out.println("索引文件："+f.getCanonicalPath()); //件的真实路径
         Document doc=getDocument(f); // 获取该文件的文档(document)
         writer.addDocument(doc); // 将文档写入索引文件(IndexWriter)
     }
 
     /**
      * 获取文档,文档里再设置每个字段档的概念可类比于数据库中的一行记录)
      * 对每一个字段进行文档对象的映射
      * @param f 指定的索引文件
      */
     private Document getDocument(File f)throws Exception {
         Document doc=new Document(); // 为每个新建文档,然后添加字段
         doc.add(new TextField("contents",new FileReader(f))); //本字段(KV形式):文件f的内容
         doc.add(new TextField("fileName", f.getName(), Field.Store.YES)); // f的文件名,并将文件名存入索引文件配置默认不存)
         doc.add(new TextField("fullPath",f.getCanonicalPath(),Field.Store.YES)); //的完整路径
         return doc;
     }
     
     // 编写测试方法
     public static void main(String[] args) {
         String indexDir="D:\\lucene\\index"; // 索引输出端
         String dataDir="D:\\lucene\\data"; // 数据源
         Indexer indexer=null; //
         int numIndexed=0;
         long start=System.currentTimeMillis(); // 开始时间
         try {
             indexer = new Indexer(indexDir);
             numIndexed=indexer.index(dataDir); //获取索引的数据数量
         } catch (Exception e) {
             // TODO Auto-generated catch block
             e.printStackTrace();
         }finally{
             try {
                 indexer.close();
             } catch (Exception e) {
                 // TODO Auto-generated catch block
                 e.printStackTrace();
             }
         }
         long end=System.currentTimeMillis(); // 结束时间
         System.out.println("索引："+numIndexed+" 个文件 花费了"+(end-start)+" 毫秒");
     }
 }